home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
turbovis
/
tvtoys04.zip
/
HELPFILE.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-12-18
|
26KB
|
1,072 lines
(***************************************************************************
Helpfile unit
Improved help file
PJB November 7, 1993, Internet mail to d91-pbr@nada.kth.se
Free patches, use at your own risk. All warranties void.
If even more modified, please state so if you pass this around.
This HelpFile patched to allow back tracking and external access to
help topics (search for "HelpExtensions").
Some Borland bugs fixed (search for "fix"). Handles empty topics.
Doesn't spill long topic links any more.
Define RangeFix to fix more Borland bugs (search for "Int->Word fix"):
Borland sometimes uses integers for help topics even though they are
words, RangeFix changes them into words so you can compile with $R+.
If you define RangeFix, you'll get a compile error if you try to
compile TVHC. In that case, modify TVHC to this (change to RefType):
procedure HandleCrossRefs(var S: TStream; XRefValue: RefType); far; { Int->Word fix }
This HelpFile requires an exact topic match. To respond to a range of
help topics, define several in a row like this:
.topic First,F2,F3,F4
Added PPalette casts, Config and Prefs. Remembers last selected topic.
***************************************************************************)
{************************************************}
{ }
{ Turbo Vision Demo }
{ Copyright (c) 1992 by Borland International }
{ }
{************************************************}
unit HelpFile;
{$I toyCfg}
{$IFDEF DPMI}
{$B-,X+}
{$ELSE}
{$B-,F+,O+,X+}
{$ENDIF}
{$IFNDEF RangeFix}
{$R-} (* Borland bugs require $R- *)
{$ENDIF}
interface
uses
Drivers, Objects, Views,
toyPrefs;
const
CHelpColor = #$37#$3F#$3A#$13#$13#$30#$3E#$1E;
CHelpBlackWhite = #$07#$0F#$07#$70#$70#$07#$0F#$70;
CHelpMonochrome = #$07#$0F#$07#$70#$70#$07#$0F#$70;
CHelpViewer = #6#7#8;
CHelpWindow = #128#129#130#131#132#133#134#135;
type
{$IFDEF RangeFix}
RefType = Word; { Int->Word fix }
{$ELSE}
RefType = Integer;
{$ENDIF}
{ TParagraph }
PParagraph = ^TParagraph;
TParagraph = record
Next: PParagraph;
Wrap: Boolean;
Size: Word;
Text: record end;
end;
{ THelpTopic }
TCrossRef = record
Ref: Word;
Offset: Integer;
Length: Byte;
end;
PCrossRefs = ^TCrossRefs;
TCrossRefs = array[1..10000] of TCrossRef;
TCrossRefHandler = procedure (var S: TStream; XRefValue: RefType); { Int->Word fix }
PHelpTopic = ^THelpTopic;
THelpTopic = object(TObject)
constructor Init;
constructor Load(var S: TStream);
destructor Done; virtual;
procedure AddCrossRef(Ref: TCrossRef);
procedure AddParagraph(P: PParagraph);
procedure GetCrossRef(I: Integer; var Loc: TPoint; var Length: Byte;
var Ref: Word);
function GetLine(Line: Integer): String;
function GetNumCrossRefs: Integer;
function NumLines: Integer;
procedure SetCrossRef(I: Integer; var Ref: TCrossRef);
procedure SetNumCrossRefs(I: Integer);
procedure SetWidth(AWidth: Integer);
procedure Store(var S: TStream);
private
Paragraphs: PParagraph;
NumRefs: Integer;
CrossRefs: PCrossRefs;
Width: Integer;
LastOffset: Integer;
LastLine: Integer;
LastParagraph: PParagraph;
function WrapText(var Text; Size: Integer; var Offset: Integer;
Wrap: Boolean): String;
end;
{ THelpIndex }
PIndexArray = ^TIndexArray;
TIndexArray = array[0..16380] of LongInt;
PContextArray = ^TContextArray;
TContextArray = array[0..16380] of Word;
PHelpIndex = ^THelpIndex;
THelpIndex = object(TObject)
constructor Init;
constructor Load(var S: TStream);
destructor Done; virtual;
function Position(I: Word): Longint;
procedure Add(I: Word; Val: Longint);
procedure Store(var S: TStream);
private
Size: Word;
Used: Word;
Contexts: PContextArray;
Index: PIndexArray;
function Find(I: Word): Word;
end;
{ THelpFile }
PHelpFile = ^THelpFile;
THelpFile = object(TObject)
Stream: PStream;
Modified: Boolean;
{$IFDEF HelpExtensions}
HelpAlreadyPopped: Boolean; (* "First time" indicator *)
{$ENDIF}
constructor Init(S: PStream);
destructor Done; virtual;
function GetTopic(I: Word): PHelpTopic;
function InvalidTopic: PHelpTopic;
procedure RecordPositionInIndex(I: RefType); { Int->Word fix }
procedure PutTopic(Topic: PHelpTopic);
private
Index: PHelpIndex;
IndexPos: LongInt;
end;
{ THelpViewer }
PHelpViewer = ^THelpViewer;
THelpViewer = object(TScroller)
HFile: PHelpFile;
Topic: PHelpTopic;
Selected: Integer;
constructor Init(var Bounds: TRect; AHScrollBar,
AVScrollBar: PScrollBar; AHelpFile: PHelpFile; Context: Word);
destructor Done; virtual;
procedure ChangeBounds(var Bounds: TRect); virtual;
procedure Draw; virtual;
function GetPalette: PPalette; virtual;
procedure HandleEvent(var Event: TEvent); virtual;
end;
{ THelpWindow }
PHelpWindow = ^THelpWindow;
THelpWindow = object(TWindow)
constructor Init(HFile: PHelpFile; Context: Word);
function GetPalette: PPalette; virtual;
end;
const
RHelpTopic: TStreamRec = (
ObjType: 10000;
VmtLink: Ofs(TypeOf(THelpTopic)^);
Load: @THelpTopic.Load;
Store: @THelpTopic.Store
);
const
RHelpIndex: TStreamRec = (
ObjType: 10001;
VmtLink: Ofs(TypeOf(THelpIndex)^);
Load: @THelpIndex.Load;
Store: @THelpIndex.Store
);
procedure RegisterHelpFile;
procedure NotAssigned(var S: TStream; Value: RefType); { Int->Word fix }
const
CrossRefHandler: TCrossRefHandler = NotAssigned;
implementation
{ THelpTopic }
constructor THelpTopic.Init;
begin
inherited Init;
LastLine := MaxInt;
end;
constructor THelpTopic.Load(var S: TStream);
procedure ReadParagraphs;
var
I, Size: Integer;
PP: ^PParagraph;
begin
S.Read(I, SizeOf(I));
PP := @Paragraphs;
while I > 0 do
begin
S.Read(Size, SizeOf(Size));
GetMem(PP^, SizeOf(PP^^) + Size);
PP^^.Size := Size;
S.Read(PP^^.Wrap, SizeOf(Boolean));
S.Read(PP^^.Text, Size);
PP := @PP^^.Next;
Dec(I);
end;
PP^ := nil;
end;
procedure ReadCrossRefs;
begin
S.Read(NumRefs, SizeOf(Integer));
GetMem(CrossRefs, SizeOf(TCrossRef) * NumRefs);
if CrossRefs <> nil then
S.Read(CrossRefs^, SizeOf(TCrossRef) * NumRefs);
end;
begin
inherited Init; { BUG fix, for empty topics }
ReadParagraphs;
ReadCrossRefs;
{ Width:=0 handled by init }
LastLine := MaxInt;
end;
destructor THelpTopic.Done;
procedure DisposeParagraphs;
var
P, T: PParagraph;
begin
P := Paragraphs;
while P <> nil do
begin
T := P;
P := P^.Next;
FreeMem(T, SizeOf(T^) + T^.Size);
end;
end;
begin
DisposeParagraphs;
FreeMem(CrossRefs, SizeOf(TCrossRef) * NumRefs);
inherited Done
end;
procedure THelpTopic.AddCrossRef(Ref: TCrossRef);
var
P: PCrossRefs;
begin
GetMem(P, (NumRefs+1) * SizeOf(TCrossRef));
if NumRefs > 0 then
begin
Move(CrossRefs^, P^, NumRefs * SizeOf(TCrossRef));
FreeMem(CrossRefs, NumRefs * SizeOf(TCrossRef));
end;
CrossRefs := P;
CrossRefs^[NumRefs] := Ref;
Inc(NumRefs);
end;
procedure THelpTopic.AddParagraph(P: PParagraph);
var
PP: ^PParagraph;
begin
PP := @Paragraphs;
while PP^ <> nil do
PP := @PP^^.Next;
PP^ := P;
P^.Next := nil;
end;
procedure THelpTopic.GetCrossRef(I: Integer; var Loc: TPoint;
var Length: Byte; var Ref: Word);
var
OldOffset, CurOffset, Offset, ParaOffset: Integer;
P: PParagraph;
Line: Integer;
begin
ParaOffset := 0;
CurOffset := 0;
OldOffset := 0;
Line := 0;
Offset := CrossRefs^[I]